#include<iostream>
#include<array>
#include<random>
#include<vector>
#include "map.hh"
#include "locations/classroom.hh"
#include "locations/corridor.hh"
#include "locations/hall.hh"
#include "locations/hidden_specimenRoom.hh"
#include "locations/Lab.hh"
#include "locations/office.hh"
#include "locations/stairwell.hh"

using std::cout;
using std::endl;
using std::string;
using std::array;


Map& Map::generate_map(){
    for(int i=1;i<9;i++){
        this->map[1][i]=3;
        this->map[4][i]=3;
        this->map[7][i]=3;     //corridor
    }
    this->map[0][1]=1;
    this->map[0][7]=1;         //hall
    this->map[1][8]=6;
    this->map[4][8]=6;
    this->map[7][8]=6;
    this->map[1][0]=6;
    this->map[4][0]=6;
    this->map[7][0]=6;         //stairwell
    int a=(rand() % (7))+ 1;
    this->map[6][a]=4;          //office
    int b=(rand() % (7))+ 1;
    this->map[3][b]=5;           //specimen
    int c;
    for(int i=0;i<15;i++){
        c=(rand()%(63))+ 1;
        while(this->map[c%9][c%7+1]!=0){     //1<=j<=7 0<=i<=9
            c=(rand() % (63))+ 1;
        }
        this->map[c%9][c%7+1]=2;  //classroom
    }
    return *this;
}
void Map::show_map() const{ 
    for(int i=0;i<this->map.size();i++){
        if(i%3==0){
            cout<<this->s1<<endl;
            cout<<"| ";
            cout<<"Ground "<<i/3+1<<this->s2<<endl;
            cout<<"| ";
            cout<<"--left     :";
        }else if(i%3==1){
            cout<<"| ";
            cout<<"--corridor :";
        }else if(i%3==2){
            cout<<"| ";
            cout<<"--right    :";
        }
        for(int j=0;j<this->map[i].size();j++){
            if(this->map[i][j]!=0){
                cout<<this->location_name[this->map[i][j]-1]<<"   ";
            }else{
                cout<<"             ";
            }
            
        }
        cout<<"|"<<endl;
    }            
    cout<<this->s1<<endl;

}
Map& Map::add_visted(int x,int y){
    this->map_visited[x][y]=true;
    //cout<<endl<<x<<y<<endl;
    if(this->map[x][y]==3){
        this->map_visited[x-1][y]=true;
        //cout<<x-1<<" "<<y<<endl;
        this->map_visited[x+1][y]=true;
        //cout<<x+1<<" "<<y<<endl;
        if(y>0){
            this->map_visited[x][y-1]=true;
            //cout<<x<<" "<<y-1<<endl;
    
        }
        if(y<this->map[x].size()){
            this->map_visited[x][y+1]=true;
            //cout<<x<<" "<<y+1<<endl;
    
        }

    }
    
    if(this->map[x][y]==6&&x+3<this->map_visited.size()){
        this->map_visited[x+3][y]=true;
        //cout<<x+3<<" "<<y<<endl;
        
    }
    return *this;
}
Map& Map::add_searched(int x,int y){
    this->map_searched[x][y]=true;
    return *this;
}
void Map::show_location(int x,int y) {
    for(int i=0;i<this->map.size();i++){
        if(i%3==0){
            cout<<this->s1<<endl;
            cout<<"| ";
            cout<<"Ground "<<i/3+1<<this->s2<<endl;
            cout<<"| ";
            cout<<"--left     :";
        }else if(i%3==1){
            cout<<"| ";
            cout<<"--corridor :";
        }else if(i%3==2){
            cout<<"| ";
            cout<<"--right    :";
        }        
        for(int j=0;j<this->map[i].size();j++){
            if(i==x&&j==y){
                cout<<"Player       ";
            }else if(this->map[i][j]!=0&&this->map_visited[i][j]){
                cout<<this->location_name[this->map[i][j]-1]<<"   ";
            }else if(this->map_visited[i][j]){
                cout<<"             ";
            }else if(this->map[i][j]==3||this->map[i][j]==6){
                cout<<this->location_name[this->map[i][j]-1]<<"   ";
            }else if(j==0||j==this->map[i].size()-1){
                cout<<"             ";
            }else if(!this->map_visited[i][j]){
                cout<<"      ?      ";
            }
        }
        cout<<"|"<<endl;
    };
    cout<<this->s1<<endl;
 }

 Location* Map::player_location(int x, int y) const {
    if (this->map[x][y] == 1) {
        return new Hall();
    }
    if (this->map[x][y] == 2) {
        Classroom* c = new Classroom();
        if (map_searched[x][y] == true) {
            c->have_serached = true;
        }
        return c;
    }
    if (this->map[x][y] == 3) {
        return new Corridor();
    }
    if (this->map[x][y] == 4) {
        return new Office();
    }
    if (this->map[x][y] == 5) {
        return new Lab();
    }
    if (this->map[x][y] == 6) {
        return new Stairwell();
    }
    
    return nullptr; 
}

vector<char> Map::display_menu(int x,int y){
    cout<<endl;
    cout<<"Move menu:"<<endl;
    int i=1;
    std::vector<char> movemenu={'i','u','q','v','l'};
    
    if(this->map[x][y]==1||this->map[x][y]==2||this->map[x][y]==4||this->map[x][y]==5){
        cout<<i<<". x---leave and back the corridor"<<endl;
        i++;
        movemenu.push_back('x');
    }
    
    if(this->map[x][y]==3){
        if(y>0){
            cout<<i<<". a---Walk south and enter "<<this->location_name[this->map[x][y-1]-1]<<endl;
            i++;
            movemenu.push_back('a');

        }
        if(y<this->map[x].size()){
            cout<<i<<". d---Walk north and enter "<<this->location_name[this->map[x][y+1]-1]<<endl;
            i++;
            movemenu.push_back('d');
            
        }
        if(this->map[x-1][y]!=0){
            cout<<i<<". w---Walk west and enter "<<this->location_name[this->map[x-1][y]-1]<<endl;
            i++;
            movemenu.push_back('w');

        }
        if(this->map[x+1][y]!=0){
            cout<<i<<". s---Walk east and enter "<<this->location_name[this->map[x+1][y]-1]<<endl;
            i++;
            movemenu.push_back('s');

        }

    }
    if(this->map[x][y]==6){
        if(y<this->map[x][y]){
            cout<<i<<". d---go ahead to the "<<this->location_name[this->map[x][y+1]-1]<<endl;
            i++;
            movemenu.push_back('d');

        }
        if(y>0){
            cout<<i<<". a---turn back to the "<<this->location_name[this->map[x][y-1]-1]<<endl;
            movemenu.push_back('a');
            i++;
        }
        if(x<map.size()-2){
            cout<<i<<". n---upstair "<<endl;
            movemenu.push_back('n');
            i++;
        }
        if(x>1){
            cout<<i<<". m---downstair "<<endl;
            movemenu.push_back('m');
            i++;
        }
    }
    cout<<i<<". i---Check the items in the inventory"<<endl;
    i++;
    cout<<i<<". u---Replenish your health points with snacks( Notice: Snacks can reduce the maximum health value)"<<endl;
    i++;
    cout<<i<<". q---Quit the game"<<endl;
    i++;
    cout<<i<<". v---View the current status"<<endl;
    i++;
    cout<<i<<". l---Display the map"<<endl;
    i++;
    return movemenu;
}






